#!/usr/bin/env python3
# -*- coding:utf-8 -*-
#############################################################################
# Copyright (c) 2020 Huawei Technologies Co.,Ltd.
#
# openGauss is licensed under Mulan PSL v2.
# You can use this software according to the terms
# and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
#          http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# ----------------------------------------------------------------------------
# Description  : gs_checkos is a utility to check and set cluster OS information.
#############################################################################

import os
import sys
import time
import subprocess
from datetime import datetime, timedelta

sys.path.append(sys.path[0] + '/../lib')
from gspylib.threads.SshTool import SshTool
from gspylib.common.GaussLog import GaussLog
from gspylib.common.Common import DefaultValue
from gspylib.common.OMCommand import OMCommand
from gspylib.common.DbClusterInfo import dbClusterInfo
from gspylib.common.ErrorCode import ErrorCode
from gspylib.common.ParameterParsecheck import Parameter
from base_utils.os.file_util import FileUtil
from base_utils.os.net_util import NetUtil
from domain_utils.domain_common.cluster_constants import ClusterConstants
from base_utils.common.constantsbase import ConstantsBase
from base_utils.os.user_util import UserUtil
from domain_utils.cluster_file.cluster_config_file import ClusterConfigFile
from base_utils.os.env_util import EnvUtil


#############################################################################
# Global variables
#   gs_checkos_version: the gs_checkos verion number
#   g_opts: globle option
#   g_logger: globle logger
#   g_sshTool: globle ssh interface
#   g_OSCheckOpts: options about all checking and setting items
#   DEFAULT_INTERVAL: default space number
#   CHECK_ITEMNUMLIST: checking item list
#   SET_ITEMNUMLIST: setting item list
#   LOG_DIR: the log directory about gs_checkos
#############################################################################
g_opts = None
g_logger = None
g_sshTool = None
host = None
g_clusterInfo = None
g_OSCheckOpts = {
    'A1': ['Checking items', '[ OS version status ]', 'Normal', 'OK', 'OK'],
    'A2': ['Checking items', '[ Kernel version status ]', 'Normal', 'OK',
           'OK'],
    'A3': ['Checking items', '[ Unicode status ]', 'Normal', 'OK', 'OK'],
    'A4': ['Checking items', '[ Time zone status ]', 'Normal', 'OK', 'OK'],
    'A5': ['Checking items', '[ Swap memory status ]', 'Normal', 'OK', 'OK'],
    'A6': ['Checking items', '[ System control parameters status ]', 'Normal',
           'OK', 'OK'],
    'A7': ['Checking items', '[ File system configuration status ]', 'Normal',
           'OK', 'OK'],
    'A8': ['Checking items', '[ Disk configuration status ]', 'Normal', 'OK',
           'OK'],
    'A9': ['Checking items', '[ Pre-read block size status ]', 'Normal', 'OK',
           'OK'],
    'A10': ['Checking items', '[ IO scheduler status ]', 'Normal', 'OK',
            'OK'],
    'A11': ['Checking items', '[ Network card configuration status ]',
            'Normal', 'OK', 'OK'],
    'A12': ['Checking items', '[ Time consistency status ]', 'Normal', 'OK',
            'OK'],
    'A13': ['Checking items', '[ Firewall service status ]', 'Normal', 'OK',
            'OK'],
    'A14': ['Checking items', '[ THP service status ]', 'Normal', 'OK', 'OK'],
    'B1': ['Setting items', '[ Set system control parameters ]', 'Normal',
           'OK', 'OK'],
    'B2': ['Setting items', '[ Set file system configuration value ]',
           'Normal', 'OK', 'OK'],
    'B3': ['Setting items', '[ Set pre-read block size value ]', 'Normal',
           'OK', 'OK'],
    'B4': ['Setting items', '[ Set IO scheduler value ]', 'Normal', 'OK',
           'OK'],
    'B5': ['Setting items', '[ Set network card configuration value ]',
           'Normal', 'OK', 'OK'],
    'B6': ['Setting items', '[ Set THP service ]', 'Normal', 'OK', 'OK'],
    'B7': ['Setting items', '[ Set RemoveIPC value ]', 'Normal', 'OK', 'OK'],
    'B8': ['Setting items', '[ Set Session Process ]', 'Normal', 'OK', 'OK']}
DEFAULT_INTERVAL = 60
DEFAULT_CONSISTENCY_INTERVAL = 6
CHECK_ITEMNUMLIST = ['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9',
                     'A10', 'A11', 'A12', 'A13', 'A14']
NO_ROOT_USER_CHECK_ITEMNUMLIST = ['A1', 'A2', 'A3', 'A4', 'A5', 'A8', 'A12', 'A13']
SET_ITEMNUMLIST = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8']
LOG_DIR = "/tmp/gs_checkos"
Local_CheckOs = ""
Local_Check = ""
#######################################################
# action option strings
ACTION_CHECK_OS_VERSION = "Check_OS_Version"
ACTION_CHECK_KERNEL_VERSION = "Check_Kernel_Version"
ACTION_CHECK_UNICODE = "Check_Unicode"
ACTION_CHECK_TIMEZONE = "Check_TimeZone"
ACTION_CHECK_SYSCTL_PARAMETER = "Check_SysCtl_Parameter"
ACTION_CHECK_DISK_CONFIGURE = "Check_Disk_Configure"
ACTION_CHECK_BLOCKDEV_CONFIGURE = "Check_BlockDev_Configure"
ACTION_CHECK_LOGICAL_BLOCK = "Check_Logical_Block"
ACTION_CHECK_IO_REQUEST = "Check_IO_Request"
ACTION_CHECK_ASYNCHRONOUS_IO_REQUEST = "Check_Asynchronous_IO_Request"
ACTION_CHECK_IO_CONFIGURE = "Check_IO_Configure"
ACTION_CHECK_NETWORK_CONFIGURE = "Check_Network_Configure"
ACTION_CHECK_NETWORK_BOND_MODE = "Check_Network_Bond_Mode"
ACTION_CHECK_SWAP_MEMORY_CONFIGURE = "Check_Swap_Memory_Configure"
ACTION_CHECK_FILESYSTEM_CONFIGURE = "Check_FileSystem_Configure"
ACTION_CHECK_TIME_CONSISTENCY = "Check_Time_Consistency"
ACTION_CHECK_FIREWALL_SERVICE = "Check_Firewall_Service"
ACTION_CHECK_THP_SERVICE = "Check_THP_Service"

ACTION_SET_SYSCTL_PARAMETER = "Set_SysCtl_Parameter"
ACTION_SET_FILESYSTEM_CONFIGURE = "Set_FileSystem_Configure"
ACTION_SET_NETWORK_CONFIGURE = "Set_Network_Configure"
ACTION_SET_THP_SERVICE = "Set_THP_Service"
ACTION_SET_REMOVEIPC_VALUE = "Set_RemoveIPC_Value"
ACTION_SET_SESSION_PROCESS = "Set_Session_Process"
ACTION_SET_BLOCKDEV_CONFIGURE = "Set_BlockDev_Configure"
ACTION_SET_LOGICAL_BLOCK = "Set_Logical_Block"
ACTION_SET_IO_CONFIGURE = "Set_IO_Configure"
ACTION_SET_IO_REQUEST = "Set_IO_REQUEST"
ACTION_SET_ASYNCHRONOUS_IO_REQUEST = "Set_Asynchronous_IO_Request"

#######################################################
class CmdOptions():
    """
    init the command options
    """

    def __init__(self):
        self.hostnamestr = ""
        self.itemstr = ""
        self.hostlistfile = ""
        self.hostnameList = []
        self.outputfile = ""
        self.logFile = ""
        self.localLog = ""
        self.set = False
        self.detail = False
        self.detail_all = False
        self.item_detail = []
        self.confFile = ""
        self.localMode = False
        self.skip_cgroup_set = False
        self.skip_item_num_str = ""
        self.skip_item_num_list = []

    #########################################################

# Init global log
#########################################################
def initGlobals():
    """
    init the global parameter g_logger and g_sshTool
    """
    global g_logger
    global g_sshTool
    global g_clusterInfo
    g_logger = GaussLog(g_opts.logFile, "gs_checkos")
    dirName = os.path.dirname(g_opts.logFile)
    g_opts.localLog = os.path.join(dirName, ClusterConstants.LOCAL_LOG_FILE)
    if not g_opts.localMode:
        g_sshTool = SshTool(g_opts.hostnameList, g_logger.logFile,
                            DefaultValue.TIMEOUT_PSSH_CHECK)
    g_clusterInfo = dbClusterInfo()
    if (g_opts.confFile != ""):
        g_clusterInfo.initFromXml(g_opts.confFile)


#############################################################################
# Parse and check parameters
#############################################################################
def usage():
    """
gs_checkos is a utility to check and set cluster OS information.

Usage:
  gs_checkos -? | --help
  gs_checkos -V | --version
  gs_checkos -i ITEM [-f HOSTFILE] [-h HOSTNAME] [-X XMLFILE] [--detail] [-o OUTPUT] [-l LOGFILE] [--skip-item-num=ITEMNUM]

General options:
  -i                              Item number. To check all items, enter  "-i A". To set all parameters, enter "-i B".
                                  To check multiple status, enter the items in the following format: "-i A1,A2,A3".
  -f                              File listing names of all the hosts to connect to. The host names are separated by line breaks.
  -h                              Name of the host to connect to.
  -X                              Configuration file of the cluster.
     --detail                     Show detailed information.
     --skip-item-num=ITEMNUM      Skip the specified item number.
  -o                              Save the result to the specified file.
  -l                              Path of log file.
  -? --help                       Show help information for this utility, and exit the command line mode.
  -V --version                    Show version information.


Item number description:
  'A1':[ OS version status ]
  'A2':[ Kernel version status ]
  'A3':[ Unicode status ]
  'A4':[ Time zone status ]
  'A5':[ Swap memory status ]
  'A6':[ System control parameters status ]
  'A7':[ File system configuration status ]
  'A8':[ Disk configuration status ]
  'A9':[ Pre-read block size status ]
  'A10':[ IO scheduler status ]
  'A11':[ Network card configuration status ]
  'A12':[ Time consistency status ]
  'A13':[ Firewall service status ]
  'A14':[ THP service status ]
  'B1':[ Set system control parameters ]
  'B2':[ Set file system configuration value ]
  'B3':[ Set pre-read block size value ]
  'B4':[ Set IO scheduler value ]
  'B5':[ Set network card configuration value ]
  'B6':[ Set THP service ]
  'B7':[Set RemoveIPC value]
  'B8':[Set Session Process]
    """
    print(usage.__doc__)


def parseHostnameOpts(value):
    """
    parse hostnames by value
    """
    if (len(value) > 1):
        for val in value:
            val = val.strip()
            if val != "" and val not in g_opts.hostnameList:
                g_opts.hostnameList.append(val)
    else:
        g_opts.hostnameList.append(value[0])


def parseItemOpts(itemList):
    """
    parse items by value
    """
    value = []
    for val in itemList:
        if (len(val.split(',')) > 1):
            for i in val.split(','):
                value.append(i)
        else:
            value.append(val)
    if (len(value) > 1):
        for val in value:
            val = val.strip().upper()
            if (val in CHECK_ITEMNUMLIST or val.upper() == "A" or
                    val in SET_ITEMNUMLIST or val.upper() == "B"):
                if val not in g_opts.item_detail:
                    g_opts.item_detail.append(val)
            else:
                GaussLog.exitWithError(
                    ErrorCode.GAUSS_500["GAUSS_50004"] % 'i')
    else:
        value = value[0].upper()
        if (value in CHECK_ITEMNUMLIST or value == "A" or
                value in SET_ITEMNUMLIST or value == "B"):
            if value not in g_opts.item_detail:
                g_opts.item_detail.append(value)
        else:
            GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50004"] % 'i')


def parseCommandLine():
    """
    Parse command line and save to global variable
    """
    global g_opts
    g_opts = CmdOptions()

    ParaObj = Parameter()
    ParaDict = ParaObj.ParameterCommandLine("checkos")
    if (ParaDict.__contains__("helpFlag")):
        usage()
        sys.exit(0)
    if (ParaDict.__contains__("logFile")):
        g_opts.logFile = ParaDict.get("logFile")
    if (ParaDict.__contains__("confFile")):
        g_opts.confFile = ParaDict.get("confFile")
    if (ParaDict.__contains__("nodename")):
        g_opts.hostnamestr = ParaDict.get("nodename")
    if (ParaDict.__contains__("hostfile")):
        g_opts.hostlistfile = ParaDict.get("hostfile")
    if (ParaDict.__contains__("outFile")):
        g_opts.outputfile = ParaDict.get("outFile")
    if (ParaDict.__contains__("itemstr")):
        g_opts.itemstr = ParaDict.get("itemstr")
    if (ParaDict.__contains__("show_detail")):
        g_opts.detail = ParaDict.get("show_detail")
    if (ParaDict.__contains__("skip_item_num")):
        g_opts.skip_item_num_str = ParaDict.get("skip_item_num")

def get_user_info():
    """
    function: get user
    input: NA
    output: NA
    """
    if os.getuid() != 0:
        user_info = UserUtil.getUserInfo()
        g_opts.user = user_info.get("name")
        DefaultValue.checkPathVaild(g_opts.user)

def readHostFile(hostfile):
    """
    read host file to hostlist
    """
    try:
        with open(hostfile, "r") as fp:
            for readline in fp:
                hostname = readline.strip().split("\n")[0]
                if hostname != "" and hostname not in hostfile:
                    g_opts.hostnameList.append(hostname)
    except Exception as e:
        GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50204"] %
                               hostfile + " Error: \n%s" % str(e))


def checkHostList():
    """
    """
    if (g_opts.hostnamestr == "" and g_opts.hostlistfile == ""):
        g_opts.hostnameList = [NetUtil.GetHostIpOrName()]
    elif (g_opts.hostnamestr != "" and g_opts.hostlistfile != ""):
        GaussLog.exitWithError(
            ErrorCode.GAUSS_500["GAUSS_50005"] % ('h', 'f'))
    elif (g_opts.hostnamestr == "" and g_opts.hostlistfile != ""):
        if (not os.path.isfile(g_opts.hostlistfile)):
            GaussLog.exitWithError(
                ErrorCode.GAUSS_502["GAUSS_50201"] % g_opts.hostlistfile)
        else:
            readHostFile(g_opts.hostlistfile)
    else:
        parseHostnameOpts(g_opts.hostnamestr)


def checkConfigFile():
    """
    """
    if (g_opts.confFile != ""):
        if (not os.path.isfile(g_opts.confFile)):
            GaussLog.exitWithError(
                ErrorCode.GAUSS_502["GAUSS_50201"] % g_opts.confFile)

def get_checkos_log_path(log_name, xml):
    """
    function: get the checkos log path
    input: log_name, xml
    output: fullLogPath
    """
    try:
        gs_checkos_log_path = ""
        # get the log path
        configedLogPath = ClusterConfigFile.getOneClusterConfigItem("gaussdbLogPath", xml)
        DefaultValue.checkPathVaild(configedLogPath)
        # check gaussdbLogPath is not null
        if configedLogPath == "":
            gs_checkos_log_path = "%s/%s/om/%s" % (
            ClusterConstants.GAUSSDB_DIR, g_opts.user, log_name)
        else:
            gs_checkos_log_path = "%s/%s/om/%s" % (
            os.path.normpath(configedLogPath), g_opts.user, log_name)
        UserUtil.check_path_owner(gs_checkos_log_path)
        return gs_checkos_log_path
    except Exception as e:
        GaussLog.exitWithError(str(e))

def create_log_file():
    cmd = "(if [ ! -d %s ]; then mkdir -p %s -m %s; fi)" % (
                LOG_DIR, LOG_DIR, DefaultValue.KEY_DIRECTORY_MODE)
    (status, output) = subprocess.getstatusoutput(cmd)
    if (status != 0):
        GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50208"]
                            % "log of gs_checkos" + " Error: \n%s."
                            % output + "The cmd is %s" % cmd)
    g_opts.logFile = os.path.join(LOG_DIR, ClusterConstants.GS_CHECKOS_LOG_FILE)

def setLogFile():
    """
    """
    if (g_opts.logFile == ""):
        if is_root_user():
            create_log_file()
        else:
            # get gausslog from env
            gauss_log = EnvUtil.getEnv("GAUSSLOG")
            if gauss_log:
                g_opts.logFile = os.path.normpath(os.path.join(gauss_log, g_opts.user, "om", ClusterConstants.GS_CHECKOS_LOG_FILE))
            # get gausslog from xml
            elif g_opts.confFile:
                g_opts.logFile = get_checkos_log_path(ClusterConstants.GS_CHECKOS_LOG_FILE, g_opts.confFile)
                if (not os.path.isabs(g_opts.logFile)):
                    GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50213"]
                                        % g_opts.logFile)
            else:
                create_log_file()

        UserUtil.check_path_owner(g_opts.logFile)

def checkItems():
    """
    """
    if (g_opts.itemstr == ""):
        GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"] % "i" + ".")


def checkOutputFile():
    """
    """
    try:
        if (g_opts.outputfile != ""):
            DefaultValue.checkOutputFile(g_opts.outputfile)
    except Exception as e:
        GaussLog.exitWithError(str(e))


def checkParameter():
    """
    Check parameter from command line
    """
    get_user_info()
    ############################################
    # check hostlist info
    ###########################################
    checkHostList()
    # check config file
    checkConfigFile()
    if (len(g_opts.hostnameList) == 0):
        g_opts.hostnameList = [NetUtil.GetHostIpOrName()]
    g_opts.hostnameList.sort()
    checkHostnameList()
    ##########################################
    # set logfile
    ############################################
    setLogFile()
    ##########################################
    # set items
    ############################################
    checkItems()

    parseItemOpts(g_opts.itemstr)
    if (("B" in g_opts.item_detail)):
        g_opts.set = True
    else:
        for i in SET_ITEMNUMLIST:
            for j in g_opts.item_detail:
                if (j == i):
                    g_opts.set = True
                    break
    if (g_opts.set == True):
        if ("A" in g_opts.item_detail):
            GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50004"] % 'i'
                                   + " Checking items and setting items"
                                     " can't be used together.")
        for i in CHECK_ITEMNUMLIST:
            for j in g_opts.item_detail:
                if (j == i):
                    GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50004"]
                                           % 'i' + " Checking items and "
                                                   "setting items can't be"
                                                   " used together.")

    ############################################
    # check output file
    ############################################
    checkOutputFile()
    # remove skip item number
    parse_item_opts(g_opts.skip_item_num_str)

def parse_item_opts(item_str):
    """
    parse item string
    """
    if (item_str == ""):
        return
    
    for item in item_str.split(','):
        if (item.strip() not in CHECK_ITEMNUMLIST):
            GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50004"] % "-skip-item-num")
        g_opts.skip_item_num_list.append(item.strip())

def remove_skip_num(item_list):
    """
    remove skip item number
    """
    if not g_opts.skip_item_num_list:
        return item_list
    return [item for item in item_list if item not in g_opts.skip_item_num_list]

def is_root_user():
    """
    Check if current user is root
    """
    return os.getuid() == 0

def doCheckOS(itemNumber):
    """
    do the checing ation by item
    """
    if (itemNumber == 'A1'):
        checkOSVersion()
    elif (itemNumber == 'A2'):
        checkKernelVersion()
    elif (itemNumber == 'A3'):
        checkUnicode()
    elif (itemNumber == 'A4'):
        checkTimeZone()
    elif (itemNumber == 'A5'):
        checkMemoryUsage()
    elif (itemNumber == 'A6'):
        checkSysCtlParameter()
    elif (itemNumber == 'A7'):
        checkFileSystemConfigure()
    elif (itemNumber == 'A8'):
        checkDiskConfigure()
    elif (itemNumber == 'A9'):
        checkBlockDevConfigure()
        checkLogicalBlock()
    elif (itemNumber == 'A10'):
        checkIOrequestqueue()
        checkMaxAsyIOrequests()
        checkIOConfigure()
    elif (itemNumber == 'A11'):
        checkNetworkConfigure()
    elif (itemNumber == 'A12'):
        checkTimeConsistency()
    elif (itemNumber == 'A13'):
        checkFirewallService()
    elif (itemNumber == 'A14'):
        checkTHPService()

def doSetOS(itemNumber):
    """
    do the setting ation by item
    """
    if (itemNumber == 'B1'):
        setSysCtlParameter()
    elif (itemNumber == 'B2'):
        setFileSystemConfigure()
    elif (itemNumber == 'B3'):
        setLogicalBlock()
        setBlockDevConfigure()
    elif (itemNumber == 'B4'):
        setIOrequestqueue()
        setMaxAsyIOrequests()
        setIOConfigure()
    elif (itemNumber == 'B5'):
        setNetworkConfigure()
    elif (itemNumber == 'B6'):
        setTHPService()
    elif (itemNumber == 'B7'):
        setRemoveIPCValue()
    elif (itemNumber == 'B8'):
        setSessionProcess()


def checkOSVersion():
    """
    check OS version
    make sure that the OS vesion is in SuSE11 sp1/2/3/4, SuSE12 sp0/1/2/3 or Redhat(centos) 6.4/6.5/6.5/6.7/6.8/6.9/7.0/7.1/7.2/7.3/7.4/7.5
    If it is local, skipping. Else the OS version from all nodes are same
    information type like this:
        True SuSE11SP1 SuSE_11_SP1_64bit
        False SuSE SuSE_10_SP4_64bit
    """
    g_logger.debug("Checking OS version.")
    try:
        cmd = "%s -t %s -l %s" % (
        Local_CheckOs, ACTION_CHECK_OS_VERSION, g_opts.localLog)
        (status, output, outputMap) = getCmdOutput(cmd)
        parRes = ""
        detail_msg = ""
        for node in list(status.keys()):
            outputMap[node] = outputMap[node].strip().split("\n")[0].strip()
        for node in list(status.keys()):
            if ((status[node] != DefaultValue.SUCCESS)):
                g_logger.logExit("[%s]: \n" % node +
                                 ErrorCode.GAUSS_516["GAUSS_51632"] % cmd +
                                 " Error: \n%s" % outputMap[node].strip())
            if ((status[node] == DefaultValue.SUCCESS) and
                    (outputMap[node].strip().split(' ')[0].strip()
                     == str(False))):
                g_OSCheckOpts['A1'][2] = 'Abnormal'
                parRes += "[%s]\n%s\n" % (
                    node, outputMap[node].strip().split(' ')[2].strip())
                detail_msg += "[%s]\n%s [Abnormal]\n" % (
                    node, outputMap[node].strip().split(' ')[2].strip())

        if ((parRes == "") and (len(list(status.keys())) > 1)):
            nodeValue = list(status.keys())[0].strip()
            mixedType = outputMap[nodeValue].strip().split(' ')[1].strip()
            platformStr = outputMap[nodeValue].strip().split(' ')[2].strip()
            sshresult = ""
            if (mixedType == ""):
                g_OSCheckOpts['A1'][2] = 'Abnormal'
                parRes += "[%s]\n%s\n" % (
                nodeValue, "Failed to obtain platform information.")
                detail_msg += "[%s]\n%s [Abnormal]\n" % (
                    nodeValue, "Failed to obtain platform information.")
            else:
                for node in list(status.keys()):
                    if ((status[node] == DefaultValue.SUCCESS) and (
                            outputMap[node].strip().split(' ')[
                                1].strip() != mixedType)):
                        g_OSCheckOpts['A1'][2] = 'Abnormal'
                        sshresult = "failed"
                        parRes += "[%s]\n%s\n" % (
                            node, outputMap[node].strip().split(' ')[2].strip())
                        detail_msg += "[%s]\n%s [Abnormal]\n" % (
                            node, outputMap[node].strip().split(' ')[2].strip())
                if (sshresult == "failed"):
                    parRes = "[%s]\n%s\n%s" % (nodeValue, platformStr, parRes)
        if (g_OSCheckOpts['A1'][2] == 'Abnormal'):
            g_OSCheckOpts['A1'][3] = "\n%s" % parRes
        else:
            parRes = ""
            for node in list(status.keys()):
                parRes += "        [%s]\n        %s\n" % (
                    node, outputMap[node].strip().split(' ')[2].strip())
                detail_msg += "        [%s]\n        %s [Normal]\n" % (
                    node, outputMap[node].strip().split(' ')[2].strip())
            g_OSCheckOpts['A1'][3] = "\n%s" % parRes
        g_OSCheckOpts['A1'][4] = "\n%s" % detail_msg

    except Exception as e:
        g_logger.debug(str(e))
    g_logger.debug("Successfully checked OS version.")


def performEnvCheck(action_item, failed_mesg, success_mesg, item_num,
                    warning_level, configFile=""):
    """
    action_item   :     action item
    failed_mesg   :     failed message information
    success_mesg  :     success message information
    item_num      :     item number
    warning_level :     warning level, warning or Abnormal
    """
    ssh_config_tmp = ""
    outputMap = {}
    try:
        if (configFile != ""):
            cmd = "%s -t %s -X '%s' -l '%s'" % (
            Local_CheckOs, action_item, configFile, g_opts.localLog)
        else:
            cmd = "%s -t %s -l '%s'" % (
            Local_CheckOs, action_item, g_opts.localLog)

        if action_item == ACTION_CHECK_UNICODE:
            try:
                # Generate an empty file as a configuration file
                ssh_config_tmp = getTmpFile()
                FileUtil.createFile(ssh_config_tmp)

                # Execute the ssh command with an empty configuration file when checking the encoding format
                (status, output, outputMap) = getCmdOutput(cmd,
                                                           ssh_config_tmp)

                # Clean up the generated empty configuration file
                FileUtil.removeFile(ssh_config_tmp)
            except Exception as e:
                if os.path.exists(ssh_config_tmp):
                    FileUtil.removeFile(ssh_config_tmp)
                g_logger.debug(
                    "Execute ssh cmd [%s] with ssh_config exception." % cmd)
                raise Exception(str(e))
        else:
            (status, output, outputMap) = getCmdOutput(cmd)
        parRes = ""
        detail_msg = ""

        for node in list(status.keys()):
            if (status[node] != DefaultValue.SUCCESS):
                g_logger.logExit("[%s]: \n" % node +
                                 ErrorCode.GAUSS_516["GAUSS_51632"] % cmd +
                                 " Error: \n%s" % outputMap[node].strip())
            if (outputMap[node].strip() == ''):
                raise Exception("[%s]\n%s\n" % (node, "The result is Null"))
            if ("not same" in outputMap[node].strip()):
                raise Exception(
                    "[%s]\n%s\n" % (node, outputMap[node].strip()))

        if ((len(list(status.keys())) > 1)):
            nodeValue = list(status.keys())[0].strip()
            keystr = outputMap[nodeValue].strip().split()[1].strip()
            sshresult = ""
            if (keystr == ""):
                g_OSCheckOpts[item_num][2] = '%s' % warning_level
                parRes += "        [%s]\n        %s\n" % (
                    nodeValue, failed_mesg)
                detail_msg += "        [%s]\n        %s\n" % (
                    nodeValue, failed_mesg)
            else:
                for node in list(status.keys()):
                    if ((status[node] == DefaultValue.SUCCESS)
                            and (outputMap[node].strip().split()[1].strip()
                                 != keystr)):
                        g_OSCheckOpts[item_num][2] = warning_level
                        sshresult = "failed"
                        parRes += "        [%s]\n        %s\n" % (
                            node, outputMap[node].strip().split()[1].strip())
                        detail_msg += "        [%s]\n        %s [%s]\n" % (
                            node, outputMap[node].strip().split()[1].strip(),
                            warning_level)
                    else:
                        detail_msg += "        [%s]\n        %s [%s]\n" % (
                            node, outputMap[node].strip().split()[1].strip(),
                            "Normal")
                if (sshresult == "failed"):
                    parRes = "        [%s]\n        %s\n%s" % (
                        nodeValue, keystr, parRes)

        if (g_OSCheckOpts[item_num][2] == warning_level):
            g_OSCheckOpts[item_num][3] = "\n%s" % parRes
            keystr = ""
        else:
            nodeValue = list(status.keys())[0].strip()
            keystr = outputMap[nodeValue].strip().split()[1].strip()
            g_OSCheckOpts[item_num][3] = "\n        %s The value is \"%s\"."\
                                         % (success_mesg, keystr)

        if g_opts.detail_all:
            if (item_num == "A11") and (keystr == "Null"):
                g_OSCheckOpts[item_num][4] = "OK"
            else:
                g_OSCheckOpts[item_num][4] = "\n%s" % detail_msg

    except Exception as e:
        g_logger.debug(str(e))
        g_logger.debug("Output: \n%s" % outputMap)
        g_OSCheckOpts[item_num][2] = warning_level
        g_OSCheckOpts[item_num][3] = "\n        %s" % failed_mesg
        g_OSCheckOpts[item_num][4] = "\n        %s" % failed_mesg


def checkKernelVersion():
    """
    Checking kernel version
    """
    g_logger.debug("Checking kernel version.")
    performEnvCheck(ACTION_CHECK_KERNEL_VERSION,
                    "Failed to obtain kernel version information.",
                    "The names about all kernel versions are same.", "A2",
                    "Warning")
    g_logger.debug("Successfully checked kernel version.")


def checkUnicode():
    """
    Checking unicode value
    """
    g_logger.debug("Checking unicode value.")
    performEnvCheck(ACTION_CHECK_UNICODE, "Failed to obtain unicode value.",
                    "The values of all unicode are same.", "A3", "Abnormal")
    g_logger.debug("Successfully checked unicode value.")


def checkTimeZone():
    """
    Checking timezone information
    """
    g_logger.debug("Checking timezone information.")
    performEnvCheck(ACTION_CHECK_TIMEZONE,
                    "Failed to obtain timezone information.",
                    "The informations about all timezones are same.", "A4",
                    "Abnormal")
    g_logger.debug("Successfully checked timezone information.")


def performCheckorSetOS(action_item, flag_str, success_mesg, item_num,
                        warning_level, configFile="", command="",
                        parameters=""):
    """
    action_item   :     action item 
    flag_str      :     failed flag string
    success_mesg  :     success message information
    item_num      :     item number
    warning_level :     warning level, warning or  Abnormal
    parameters    :     multiple strings of parameters
    """
    try:
        if command == "":
            command = Local_CheckOs
        if (configFile != ""):
            cmd = "%s -t %s -X '%s' -l '%s' %s" % (
            command, action_item, configFile, g_opts.localLog, parameters)
        else:
            cmd = "%s -t %s -l '%s' %s" % (
            command, action_item, g_opts.localLog, parameters)
        (status, output, outputMap) = getCmdOutput(cmd)
        parRes = ""
        detail_msg = ""
        for node in list(status.keys()):
            if (status[node] != DefaultValue.SUCCESS):
                g_logger.logExit("        [%s]: \n" % node +
                                 ErrorCode.GAUSS_516["GAUSS_51632"] % cmd
                                 + " Error: \n%s" % outputMap[node].strip())
            if (outputMap[node].find(flag_str) >= 0):
                g_OSCheckOpts[item_num][2] = warning_level
                parRes += "        [%s]\n%s\n" % (node, outputMap[node])
            else:
                detail_msg += "        [%s]\n%s\n" % (node, outputMap[node])
            if (outputMap[node].find("Warning reason") >= 0
                    and outputMap[node].find("Abnormal") < 0):
                if (g_OSCheckOpts[item_num][2] != "Abnormal"):
                    g_OSCheckOpts[item_num][2] = "Warning"
                parRes += "        [%s]\n%s\n" % (node, outputMap[node])
        if (parRes != ""):
            raise Exception("%s" % parRes)
        if (g_OSCheckOpts[item_num][2] != warning_level):
            g_OSCheckOpts[item_num][3] = "\n        %s" % success_mesg
        if g_OSCheckOpts[item_num][4] != "OK":
            g_OSCheckOpts[item_num][4] = formatResault(
                detail_msg, g_OSCheckOpts[item_num][4])
        else:
            g_OSCheckOpts[item_num][4] = "\n%s" % detail_msg
    except Exception as e:
        g_logger.debug(str(e))
        if (g_OSCheckOpts[item_num][2] == "Normal"):
            g_OSCheckOpts[item_num][2] = '%s' % warning_level
        g_OSCheckOpts[item_num][3] = "\n%s" % str(e)
        g_OSCheckOpts[item_num][4] = "\n%s" % str(e)


def formatResault(result_Str1, result_Str2):
    """
    get add result of to dict
    """
    result = ""
    result_list1 = result_Str1.strip("\n").split("\n\n")
    result_list2 = result_Str2.strip("\n").split("\n\n")
    for nodeInfo1 in result_list1:
        result += ("\n" + nodeInfo1.split("\n")[0])
        result += ("\n" + "\n".join(nodeInfo1.split("\n")[1:]))
        for nodeInfo2 in result_list2:
            if nodeInfo1.split("\n")[0].strip() == nodeInfo2.split("\n")[0].strip():
                result += ("\n" + "\n".join(nodeInfo2.split("\n")[1:]) + "\n")
    return result


def checkMemoryUsage():
    """
    Checking swap memory value
    """
    g_logger.debug("Checking swap memory value.")
    performCheckorSetOS(ACTION_CHECK_SWAP_MEMORY_CONFIGURE, "SwapMemory",
                        "The value about swap memory is correct.", "A5",
                        "Warning")
    g_logger.debug("Successfully checked swap memory value.")


def checkSysCtlParameter():
    """
    Checking system control parameter value
    """
    g_logger.debug("Checking system control parameter value.")
    performCheckorSetOS(ACTION_CHECK_SYSCTL_PARAMETER, "Abnormal",
                        "All values about system control  parameters are correct.",
                        "A6", "Abnormal", '', Local_Check)
    g_logger.debug("Successfully checked system control  parameter value.")


def checkFileSystemConfigure():
    """
    Checking file system configuration information
    """
    g_logger.debug("Checking file system configuration information.")
    performCheckorSetOS(ACTION_CHECK_FILESYSTEM_CONFIGURE, "Abnormal",
                        "Both soft nofile and hard nofile are correct.", "A7",
                        "Abnormal", '', Local_Check)
    g_logger.debug(
        "Successfully checked file system configuration information.")


def checkDiskConfigure():
    """
    Checking disk configuration value
    """
    g_logger.debug("Checking disk configuration value.")
    performCheckorSetOS(ACTION_CHECK_DISK_CONFIGURE, "filesystem",
                        "The value about XFS mount parameters is correct.",
                        "A8", "Warning")
    g_logger.debug("Successfully checked disk configuration value.")


def checkBlockDevConfigure():
    """
    Checking Pre-read block size value
    """
    g_logger.debug("Checking Pre-read block size value.")
    performCheckorSetOS(ACTION_CHECK_BLOCKDEV_CONFIGURE, "blockdev",
                        "The value about Pre-read block size is correct.",
                        "A9", "Warning", g_opts.confFile)
    g_logger.debug("Successfully checked Pre-read block size value.")


def checkLogicalBlock():
    """
    Checking Logical Block size value
    """
    g_logger.debug("Checking Logical Block size value.")
    performCheckorSetOS(ACTION_CHECK_LOGICAL_BLOCK, "logical_block_size",
                        "The value about Logical block size is correct.",
                        "A9", "Abnormal")
    g_logger.debug("Successfully checked Logical block size value.")


def checkIOrequestqueue():
    """
    Checking IO request queue value
    """
    g_logger.debug("Checking IO request queue value.")
    performCheckorSetOS(ACTION_CHECK_IO_REQUEST, "request",
                        "The value of IO request queue is correct.", "A10",
                        "Abnormal")
    g_logger.debug("Successfully checked IO request queue value.")


def checkMaxAsyIOrequests():
    """
    Checking Asynchronous IO request queue value
    """
    g_logger.debug("Checking Asynchronous IO request queue value.")
    performCheckorSetOS(ACTION_CHECK_ASYNCHRONOUS_IO_REQUEST, "aio-max-nr",
                        "The value of Asynchronous IO request queue is correct.",
                        "A10", "Abnormal", g_opts.confFile)
    g_logger.debug(
        "Successfully checked  Asynchronous IO request queue value.")


def checkIOConfigure():
    """
    Checking IO scheduler value
    """
    g_logger.debug("Checking IO scheduler value.")
    performCheckorSetOS(ACTION_CHECK_IO_CONFIGURE, "scheduler",
                        "The value of IO scheduler is correct.", "A10",
                        "Abnormal")
    g_logger.debug("Successfully checked IO scheduler value.")


def checkNetworkConfigure():
    """
    Checking network card configuration
    """
    g_logger.debug("Checking network card configuration.")
    performEnvCheck(ACTION_CHECK_NETWORK_BOND_MODE,
                    "Failed to obtain the networks bond mode information.",
                    "The all networks bond mode are same.", "A11", "Warning",
                    g_opts.confFile)
    if (g_OSCheckOpts["A11"][2] == "Warning"):
        g_OSCheckOpts["A11"][3] += "\n        Failed to check the network" \
                                   " bond mode."
        g_OSCheckOpts["A11"][4] = g_OSCheckOpts["A11"][3]
        return

    nodeIp = getLocalIPAddr()
    localMTU = DefaultValue.checkNetWorkMTU(nodeIp, False)
    if (str(localMTU).find("Abnormal") >= 0 or localMTU == ""):
        return
    cmdInfo = "--hostname=%s " % NetUtil.GetHostIpOrName()
    if (not g_opts.localMode):
        cmdInfo += "--MTUvalue=%s " % localMTU
    if (g_opts.confFile != "" and g_opts.confFile != None):
        cmdInfo += "--xmlfile=%s " % g_opts.confFile
    performCheckorSetOS(ACTION_CHECK_NETWORK_CONFIGURE, "Abnormal",
                        "The configuration about network card is correct.",
                        "A11", "Abnormal", g_opts.confFile, "", cmdInfo)
    g_logger.debug("Successfully checked network configuration.")


def getLocalIPAddr():
    '''
    function: get all ips from configuration file
    input : NA
    output: Ips
    '''
    Ips = ""

    if (g_opts.confFile == ""):
        localHostIp = DefaultValue.getIpByHostName()
        Ips = localHostIp
    else:
        for node in g_clusterInfo.dbNodes:
            if (node.name == NetUtil.GetHostIpOrName()):
                Ips = node.backIps[0]
    return Ips


def checkTimeConsistency():
    """
    Checking system time consistency
    """
    g_logger.debug("Checking system time consistency.")
    try:
        cmd = "%s -t %s -l %s" % (
        Local_CheckOs, ACTION_CHECK_TIME_CONSISTENCY, g_opts.localLog)
        (status, output, outputMap) = getCmdOutput(cmd)
        parRes = ""
        success_msg = "        The system time is consistent."
        for node in list(status.keys()):
            outputMap[node] = outputMap[node].strip().split("\n")[0].strip()
        for node in list(status.keys()):
            if (status[node] != DefaultValue.SUCCESS):
                g_logger.logExit("[%s]: \n" % node +
                                 ErrorCode.GAUSS_516["GAUSS_51632"] % cmd +
                                 " Error: \n%s" % outputMap[node].strip())
            if ((status[node] == DefaultValue.SUCCESS)
                    and (outputMap[node].strip().split(',')[0].strip()
                         == str(False))):
                g_OSCheckOpts['A12'][2] = 'Warning'
                parRes += "        [%s]\n        Neither nptd nor chrony was detected" \
                          " on machine and local time is \"%s\".\n"\
                          % (node,
                             outputMap[node].strip().split(',')[1].strip())

        if len(list(status.keys())) > 1:
            nodeValue = list(status.keys())[0].strip()
            keystr = outputMap[nodeValue].strip().split(',')[1].strip()
            if (keystr == ""):
                g_OSCheckOpts['A12'][2] = 'Abnormal'
                parRes += "        [%s]\n        %s\n" % (
                nodeValue, "Failed to obtain localtime information.")
            else:
                baseTime = datetime.strptime(keystr, "%Y-%m-%d %H:%M:%S")
                if g_clusterInfo.enable_dss == "on":
                    startTime = baseTime - timedelta(seconds=DEFAULT_CONSISTENCY_INTERVAL)
                    endTime = baseTime + timedelta(seconds=DEFAULT_CONSISTENCY_INTERVAL)
                else:
                    startTime = baseTime - timedelta(seconds=DEFAULT_INTERVAL)
                    endTime = baseTime + timedelta(seconds=DEFAULT_INTERVAL)
                for node in list(status.keys()):
                    if (status[node] == DefaultValue.SUCCESS):
                        tmpstr = outputMap[node].strip().split(',')[1].strip()
                        tmpTime = datetime.strptime(tmpstr,
                                                    "%Y-%m-%d %H:%M:%S")
                        if (tmpTime < startTime or tmpTime > endTime):
                            g_OSCheckOpts['A12'][2] = 'Abnormal'
                            parRes += "        [%s]\n        Variable:" \
                                          "'current system time' RealValue:" \
                                          "'%s' ExpectedValue:'%s' " \
                                          "[Abnormal]\n"\
                                          % (node, tmpstr,
                                             baseTime.strftime("%Y-%m-%d %H:%M:%S"))

        if (g_OSCheckOpts['A12'][2] == 'Normal'):
            g_OSCheckOpts['A12'][3] = "\n%s" % success_msg
            g_OSCheckOpts['A12'][4] = "\n%s" % success_msg
        else:
            g_OSCheckOpts['A12'][3] = "\n%s" % parRes
            g_OSCheckOpts['A12'][4] = "\n%s" % parRes

    except Exception as e:
        g_logger.debug(str(e))
    g_logger.debug("Successfully checked system time consistency.")


def checkFirewallService():
    """
    Checking firewall service
    """
    g_logger.debug("Checking firewall service.")
    performCheckorSetOS(ACTION_CHECK_FIREWALL_SERVICE, "firewall",
                        "The firewall service is stopped.", "A13", "Warning")
    g_logger.debug("Successfully checked firewall service.")


def checkTHPService():
    """
    Checking THP service
    """
    g_logger.debug("Checking THP service.")
    performCheckorSetOS(ACTION_CHECK_THP_SERVICE, "THP",
                        "The THP service is stopped.", "A14", "Abnormal")
    g_logger.debug("Successfully checked THP service.")

def getSetRemoveIPCValue(action_item, flag_str, flag_error, success_mesg,
                      item_num, warning_level, configFile="", command=""):
    """
       get the print information that is from setting removeipc value
       """
    try:
        if command == "":
            command = Local_CheckOs

        if (configFile != ""):
            cmd = "%s -t %s -X '%s' -l '%s'"\
                  % (command, action_item, configFile, g_opts.localLog)
        else:
            cmd = "%s -t %s -l '%s'" % (command, action_item, g_opts.localLog)
        (status, output, outputMap) = getCmdOutput(cmd)
        message = ""
        parRes = ""
        for node in list(status.keys()):
            if (status[node] != DefaultValue.SUCCESS):
                g_logger.logExit("[%s]: \n" % node +
                                 ErrorCode.GAUSS_516["GAUSS_51632"] % cmd +
                                 " Error: \n%s" % outputMap[node].strip())

            if (outputMap[node].find(flag_error) >= 0):
                parRes += "[%s]\n%s\n" % (node, outputMap[node])

            if (outputMap[node].find(flag_str) >= 0):
                message += "        [%s]\n%s\n" % (node, outputMap[node])

        if (parRes != ""):
            raise Exception("%s" % parRes)

        if (g_OSCheckOpts[item_num][2] != warning_level):
            if (message != ""):
                g_OSCheckOpts[item_num][3] = "\n%s        %s" % (
                message, success_mesg)
            else:
                g_OSCheckOpts[item_num][3] = "\n        %s" % success_mesg

    except Exception as e:
        g_logger.debug(str(e))
        g_OSCheckOpts[item_num][2] = '%s' % warning_level
        g_OSCheckOpts[item_num][3] = "\n        %s" % str(e)

def getSetSessionProcess(action_item, flag_str, flag_error, success_mesg,
                      item_num, warning_level, configFile="", command=""):
    """
       get the print information that is from setting session process
       """
    try:
        if command == "":
            command = Local_CheckOs

        if (configFile != ""):
            cmd = "%s -t %s -X '%s' -l '%s'"\
                  % (command, action_item, configFile, g_opts.localLog)
        else:
            cmd = "%s -t %s -l '%s'" % (command, action_item, g_opts.localLog)
        (status, output, outputMap) = getCmdOutput(cmd)
        message = ""
        parRes = ""
        for node in list(status.keys()):
            if (status[node] != DefaultValue.SUCCESS):
                g_logger.logExit("[%s]: \n" % node +
                                 ErrorCode.GAUSS_516["GAUSS_51632"] % cmd +
                                 " Error: \n%s" % outputMap[node].strip())

            if (outputMap[node].find(flag_error) >= 0):
                parRes += "[%s]\n%s\n" % (node, outputMap[node])

            if (outputMap[node].find(flag_str) >= 0):
                message += "        [%s]\n%s\n" % (node, outputMap[node])

        if (parRes != ""):
            raise Exception("%s" % parRes)

        if (g_OSCheckOpts[item_num][2] != warning_level):
            if (message != ""):
                g_OSCheckOpts[item_num][3] = "\n%s        %s" % (
                message, success_mesg)
            else:
                g_OSCheckOpts[item_num][3] = "\n        %s" % success_mesg

    except Exception as e:
        g_logger.debug(str(e))
        g_OSCheckOpts[item_num][2] = '%s' % warning_level
        g_OSCheckOpts[item_num][3] = "\n        %s" % str(e)


def getSetOSPrintInfo(action_item, flag_str, flag_error, success_mesg,
                      item_num, warning_level, configFile="", command=""):
    """
    get the print information that is from setting OS parameters
    """
    try:
        if command == "":
            command = Local_CheckOs

        if (configFile != ""):
            cmd = "%s -t %s -X '%s' -l '%s'"\
                  % (command, action_item, configFile, g_opts.localLog)
        else:
            cmd = "%s -t %s -l '%s'" % (command, action_item, g_opts.localLog)
        (status, output, outputMap) = getCmdOutput(cmd)
        message = ""
        parRes = ""
        for node in list(status.keys()):
            if (status[node] != DefaultValue.SUCCESS):
                g_logger.logExit("[%s]: \n" % node +
                                 ErrorCode.GAUSS_516["GAUSS_51632"] % cmd +
                                 " Error: \n%s" % outputMap[node].strip())

            if (outputMap[node].find(flag_error) >= 0):
                parRes += "[%s]\n%s\n" % (node, outputMap[node])

            if (outputMap[node].find(flag_str) >= 0):
                message += "        [%s]\n%s\n" % (node, outputMap[node])

        if (parRes != ""):
            raise Exception("%s" % parRes)

        if (g_OSCheckOpts[item_num][2] != warning_level):
            if (message != ""):
                g_OSCheckOpts[item_num][3] = "\n%s        %s" % (
                message, success_mesg)
            else:
                g_OSCheckOpts[item_num][3] = "\n        %s" % success_mesg

    except Exception as e:
        g_logger.debug(str(e))
        g_OSCheckOpts[item_num][2] = '%s' % warning_level
        g_OSCheckOpts[item_num][3] = "\n        %s" % str(e)


def setSysCtlParameter():
    """
    Setting sysctl parameter value
    """
    g_logger.debug("Setting sysctl parameter value.")
    getSetOSPrintInfo(ACTION_SET_SYSCTL_PARAMETER, "Set", "Failed", "Setting sysctl \
parameter values succeed.", "B1", "Abnormal", g_opts.confFile, Local_Check)
    g_logger.debug("Successfully setted the sysctl configuration parameters.")


def setFileSystemConfigure():
    """
    Setting file system configuration
    """
    g_logger.debug("Setting file system configuration.")
    getSetOSPrintInfo(ACTION_SET_FILESYSTEM_CONFIGURE, "Set", "Failed", "Setting soft file \
and hard file parameters succeed.", "B2", "Abnormal", g_opts.confFile,
                      Local_Check)
    g_logger.debug("Successfully setted file system configuration.")


def setBlockDevConfigure():
    """
    Setting Pre-read block size value
    """
    g_logger.debug("Setting Pre-read block size value.")
    getSetOSPrintInfo(ACTION_SET_BLOCKDEV_CONFIGURE, "blockdev", "Failed",
                      "Setting Pre-read block size value succeed.", "B3",
                      "Abnormal")
    g_logger.debug("Successfully setted  Pre-read block size value.")


def setLogicalBlock():
    """
    Setting logical block size value
    """
    g_logger.debug("Setting logical block size value.")
    performCheckorSetOS(ACTION_SET_LOGICAL_BLOCK, "Failed",
                        "Setting logical block size value succeed.", "B3",
                        "Abnormal")
    g_logger.debug("Successfully setted logical block size value.")

def setRemoveIPCValue():
    """
        Setting removeipc value
        """
    g_logger.debug("Setting RemoveIPC value.")
    getSetRemoveIPCValue(ACTION_SET_REMOVEIPC_VALUE, "Set", "Failed", "Setting sysctl \
        parameter values succeed.", "B7", "Abnormal", g_opts.confFile, Local_CheckOs)
    g_logger.debug("Sucessfully setted RemoveIPC value.")

def setSessionProcess():
    """
        Setting Session Process
        """
    g_logger.debug("Setting Session Process.")
    getSetSessionProcess(ACTION_SET_SESSION_PROCESS, "Set", "Failed", "Setting sysctl \
        parameter values succeed.", "B8", "Abnormal", g_opts.confFile, Local_CheckOs)
    g_logger.debug("Sucessfully Setted Session Process.")

def setIOConfigure():
    """
    Setting IO scheduler value
    """
    g_logger.debug("Setting IO scheduler value.")
    getSetOSPrintInfo(ACTION_SET_IO_CONFIGURE, "scheduler", "Failed",
                      "Setting IO scheduler value succeed.", "B4", "Abnormal")
    g_logger.debug("Successfully setted IO scheduler value.")


def setIOrequestqueue():
    """
    Setting IO request queue value
    """
    g_logger.debug("Setting IO request queue value.")
    performCheckorSetOS(ACTION_SET_IO_REQUEST, "failed",
                        "Setting IO request queue value succeed.", "B4",
                        "Abnormal")
    g_logger.debug("Successfully setted IO request queue value.")


def setMaxAsyIOrequests():
    """
    Setting Maximumasynchronous IO request queue value
    """
    g_logger.debug("Setting Maximumasynchronous IO request queue value.")
    performCheckorSetOS(ACTION_SET_ASYNCHRONOUS_IO_REQUEST, "failed",
                        "Setting Maximumasynchronous IO request queue value succeed.",
                        "B4", "Abnormal", g_opts.confFile)
    g_logger.debug(
        "Successfully setted  Maximumasynchronous IO request queue value.")


def setNetworkConfigure():
    """
    Setting network card configuration
    """
    g_logger.debug("Setting network card configuration.")
    getSetOSPrintInfo(ACTION_SET_NETWORK_CONFIGURE, "Set", "Failed",
                      "Seting network card configuration succeed.", "B5",
                      "Warning", g_opts.confFile)
    g_logger.debug("Successfully setted network card configuration.")


def setTHPService():
    """
    Setting THP service
    """
    g_logger.debug("Setting THP service.")
    getSetOSPrintInfo(ACTION_SET_THP_SERVICE, "Set", "Failed",
                      "Setting THP server succeed.", "B6", "Abnormal")
    g_logger.debug("Sucessfully setted THP service.")

def DisplayResultInformation(Item, output):
    """
    display the result information
    """
    if ("A" in g_opts.item_detail) or ("B" in g_opts.item_detail):
        if (Item in ("A1", "B1")):
            if (g_opts.detail):
                print("%s:\n    %s: %s %s" % (
                    g_OSCheckOpts[Item][0],
                    ("%s%s" %
                     (("%s." % Item).ljust(4),
                      g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                    g_OSCheckOpts[Item][2].ljust(10),
                    g_OSCheckOpts[Item][3].ljust(DEFAULT_INTERVAL)),
                      file=output)
            elif (g_opts.detail_all):
                print("%s:\n    %s: %s %s" %
                      (g_OSCheckOpts[Item][0],
                       ("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2].ljust(10),
                       g_OSCheckOpts[Item][4].ljust(DEFAULT_INTERVAL)),
                      file=output)
            else:
                print("%s:\n    %s: %s" %
                      (g_OSCheckOpts[Item][0],
                       ("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2]), file=output)
        else:
            if (g_opts.detail):
                print("    %s: %s %s" %
                      (("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2].ljust(10),
                       g_OSCheckOpts[Item][3].ljust(DEFAULT_INTERVAL)),
                      file=output)
            elif (g_opts.detail_all):
                print("    %s: %s %s" %
                      (("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2].ljust(10),
                       g_OSCheckOpts[Item][4].ljust(DEFAULT_INTERVAL)),
                      file=output)
            else:
                print("    %s: %s" %
                      (("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2]), file=output)
    else:
        orderItems = []
        for i in [CHECK_ITEMNUMLIST, SET_ITEMNUMLIST]:
            bb = []
            for j in g_opts.item_detail:
                if j in i:
                    bb.append(j)
            tmp = sorted(bb)
            bb = tmp
            if (bb != []):
                orderItems.append(bb[0])
        if (Item in orderItems):
            if (g_opts.detail):
                print("%s\n    %s: %s %s" %
                      (g_OSCheckOpts[Item][0],
                       ("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2].ljust(10),
                       g_OSCheckOpts[Item][3].ljust(DEFAULT_INTERVAL)),
                      file=output)
            elif (g_opts.detail_all):
                print("%s\n    %s: %s %s" %
                      (g_OSCheckOpts[Item][0],
                       ("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2].ljust(10),
                       g_OSCheckOpts[Item][4].ljust(DEFAULT_INTERVAL)),
                      file=output)
            else:
                print("%s\n    %s: %s" %
                      (g_OSCheckOpts[Item][0],
                       ("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2]), file=output)
        else:
            if (g_opts.detail):
                print("    %s: %s %s" %
                      (("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2].ljust(10),
                       g_OSCheckOpts[Item][3].ljust(DEFAULT_INTERVAL)),
                      file=output)
            elif (g_opts.detail_all):
                print("    %s: %s %s" %
                      (("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2].ljust(10),
                       g_OSCheckOpts[Item][4].ljust(DEFAULT_INTERVAL)),
                      file=output)
            else:
                print("    %s: %s" %
                      (("%s%s" %
                        (("%s." % Item).ljust(4),
                         g_OSCheckOpts[Item][1])).ljust(DEFAULT_INTERVAL),
                       g_OSCheckOpts[Item][2]), file=output)


def cmp_item(item1, item2):
    """
    sort item
    """
    if (item1[0] < item2[0]):
        return -1
    elif (item1[0] > item2[0]):
        return 1
    else:
        if (int(item1[1:]) < int(item2[1:])):
            return -1
        elif (int(item1[1:]) > int(item2[1:])):
            return 1
        else:
            return 0


def checkHostnameList():
    """
    function: check the self.hostnameList is only local hostname
    input: NA
    output:NA
    """

    # get the local hostname
    global host
    host = NetUtil.GetHostIpOrName()

    # if g_opts.hostnameList have only one value,
    # check it whether or not local hostname
    if (len(g_opts.hostnameList) == 1):
        if (g_opts.hostnameList[0] == NetUtil.GetHostIpOrName()):
            g_opts.localMode = True
            return
    try:
        # check the g_opts.hostnameList values are whether or not local IPs
        # obtain the all local IPs
        IPlist = NetUtil.getIpAddressList()
        IPlist.append(host)

        for ip in g_opts.hostnameList:
            if ip not in IPlist:
                return
        g_opts.localMode = True

    except Exception as ex:
        GaussLog.exitWithError(str(ex))


def getCmdOutput(cmd, ssh_conf=""):
    """
    function: execute the cmd and get the output
    input: cmd
    output:status, output, outputMap
    """

    if (g_opts.localMode == True):
        status = {}
        outputMap = {}
        outputCollect = []
        (statusStr, output) = subprocess.getstatusoutput(cmd)
        if (statusStr != 0):
            status[host] = "Failure"
        else:
            status[host] = "Success"
        outputMap[host] = output
    else:
        gp_path = os.path.dirname(os.path.realpath(__file__))
        (status, output) = g_sshTool.getSshStatusOutput(cmd, [], "",
                                                        "%s/../" % gp_path,
                                                        ssh_config=ssh_conf)
        outputMap = g_sshTool.parseSshOutput(g_opts.hostnameList)

    return (status, output, outputMap)


def getTmpFile():
    '''
    function : generate the check ID which is unique for once checking
    input : NA
    output : checkID
    '''
    # Get Time
    while True:
        t = time.localtime(time.time())
        dateString = time.strftime("%Y%m%d", t)
        seconds = timedelta(hours=t.tm_hour, minutes=t.tm_min,
                            seconds=t.tm_sec).seconds
        pidString = str(os.getpid())
        tmpFileName = "ssh_config" + "_" + dateString + "_"\
                      + str(seconds) + "_" + pidString
        tmpFile = os.path.join("/tmp", tmpFileName)
        if os.path.exists(tmpFile):
            time.sleep(1)
        else:
            return tmpFile

def main():
    """
    main function
    """

    global Local_CheckOs
    global Local_Check

    try:
        parseCommandLine()
        checkParameter()
        initGlobals()
        gpHome = os.path.dirname(os.path.realpath(__file__))
        Local_CheckOs = OMCommand.getLocalScript("Local_CheckOS")
        Local_Check = OMCommand.getLocalScript("Local_Check")
    except Exception as e:
        GaussLog.exitWithError(str(e))

    if ("A" in g_opts.item_detail):
        if is_root_user():
            itemList = CHECK_ITEMNUMLIST
        else:
            itemList = NO_ROOT_USER_CHECK_ITEMNUMLIST
    elif ("B" in g_opts.item_detail):
        itemList = SET_ITEMNUMLIST
    else:
        sortList = sorted(g_opts.item_detail)
        itemList = sortList

    # remove skip item
    itemList = remove_skip_num(itemList)

    fp = None
    dirName = "%s/gspylib/etc/conf" % os.path.dirname(
        os.path.realpath(__file__))
    configFile = "%s/check_list.conf" % dirName
    try:
        if (DefaultValue.checkInList(['A6', 'A7', 'A11', 'B1', 'B2', 'B5'],
                                     itemList) and
                (os.path.isfile(configFile) != True)):
            g_logger.logExit(ErrorCode.GAUSS_502["GAUSS_50201"] % configFile)
        if ((g_opts.localMode != True) and
                DefaultValue.checkInList(['A6', 'A7', 'A11', 'B1', 'B2', 'B5'],
                                         itemList)):
            g_sshTool.scpFiles(configFile, dirName, [], "", "%s/../" % gpHome)
    except Exception as ex:
        g_logger.logExit(str(ex))

    try:
        output = sys.stdout
        if (g_opts.outputfile != ""):
            basepath = os.path.dirname(g_opts.outputfile)
            if (not os.path.isdir(basepath)):
                os.makedirs(basepath, ConstantsBase.KEY_DIRECTORY_PERMISSION)
            FileUtil.createFileInSafeMode(g_opts.outputfile)
            fp = open(g_opts.outputfile, "w")
            output = fp
            g_logger.log("Performing operation system check/set."
                         " Output the result to the file %s."
                         % g_opts.outputfile)

        for item in itemList:
            if is_root_user():
                if g_opts.set:
                    doSetOS(item)
                else:
                    doCheckOS(item)
            else:
                if item not in NO_ROOT_USER_CHECK_ITEMNUMLIST:
                    break
                doCheckOS(item)

            DisplayResultInformation(item, output)

        if (fp):
            fp.flush()
            fp.close()
        if g_opts.outputfile != "":
            os.chmod(g_opts.outputfile, ConstantsBase.KEY_FILE_PERMISSION)
            g_logger.log("Operation system check/set is completed.")
    except Exception as ex:
        if fp:
            fp.flush()
            fp.close()
        g_logger.logExit(ErrorCode.GAUSS_502["GAUSS_50205"] %
                         g_opts.outputfile + "Error: %s" % str(ex))

    totalNum = 0
    abnormalNum = 0
    warningNum = 0
    for key in itemList:
        totalNum += 1
        if (g_OSCheckOpts[key][2] == "Abnormal"):
            abnormalNum += 1
        elif (g_OSCheckOpts[key][2] == "Warning"):
            warningNum += 1
    if (g_opts.set):
        g_logger.log("NOTICE: MTU value and some warning items can NOT be set."
                     " Please do it manually.")
    g_logger.log("Total numbers:%d. Abnormal numbers:%d. Warning numbers:%d."
                 % (totalNum, abnormalNum, warningNum))
    if (abnormalNum > 0):
        if (g_opts.set == False):
            g_logger.log("Do checking operation finished. Result: Abnormal.")
        else:
            g_logger.log("Do setting operation finished. Result: Abnormal.")

    g_logger.closeLog()
    sys.exit(0)


# the main entry for this script
if __name__ == '__main__':
    main()
